﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using ReportWizard.Helpers;

namespace ReportWizard.DataAccess
{
    public class LoginHost
    {
        private int Id { get; set; }
        private int UserId { get; set; }
        private string Hostname { get; set; }
        private bool Autologin { get; set; }
        private DateTime DateCreated { get; set; }

        public static UserInfo GetAutoLoginForHost(string hostname)
        {
            LoginHost lh = Select(hostname);
            return lh != null ? UserInfo.Select(lh.UserId) : null;
        }

        public static void RegisterLoginFromHost(int userId, string hostname, bool autologin)
        {
            LoginHost lh = Select(userId, hostname);
            if (lh != null)
            {
                Update(lh.Id, userId, hostname, autologin);
            }
            else
            {
                Insert(userId, hostname, autologin);
            }
        }

        private static LoginHost Select(int userId, string hostname)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand getCmd = new SqlCommand("LoginHostSelectByUserAndHost", con);
                    getCmd.CommandType = CommandType.StoredProcedure;

                    getCmd.Parameters.Add("@UserId", SqlDbType.Int).Value = userId;
                    getCmd.Parameters.Add("@Hostname", SqlDbType.VarBinary).Value = Crypto.Encrypt(hostname);

                    con.Open();
                    List<LoginHost> cList = MapFrom(getCmd.ExecuteReader());

                    if (cList != null)
                    {
                        return cList.FirstOrDefault();
                    }
                    return null;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }

        private static LoginHost Select(string hostname)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand getCmd = new SqlCommand("LoginHostSelectByHost", con);
                    getCmd.CommandType = CommandType.StoredProcedure;

                    getCmd.Parameters.Add("@Hostname", SqlDbType.VarBinary).Value = Crypto.Encrypt(hostname);

                    con.Open();
                    List<LoginHost> cList = MapFrom(getCmd.ExecuteReader());

                    if (cList != null)
                    {
                        return cList.FirstOrDefault();
                    }
                    return null;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }

        private static LoginHost Select(int id)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand getCmd = new SqlCommand("LoginHostSelect", con);
                    getCmd.CommandType = CommandType.StoredProcedure;

                    getCmd.Parameters.Add("@Id", SqlDbType.Int).Value = id;

                    con.Open();
                    List<LoginHost> cList = MapFrom(getCmd.ExecuteReader());

                    if (cList != null)
                    {
                        return cList.FirstOrDefault();
                    }
                    return null;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }

        private static int? Insert(int userId, string hostname, bool autologin)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand saveCmd = new SqlCommand("LoginHostInsert", con);
                    saveCmd.CommandType = CommandType.StoredProcedure;

                    saveCmd.Parameters.Add("@UserId", SqlDbType.Int).Value = userId;
                    saveCmd.Parameters.Add("@Hostname", SqlDbType.VarBinary).Value = Crypto.Encrypt(hostname);
                    saveCmd.Parameters.Add("@Autologin", SqlDbType.Bit).Value = autologin;
                    saveCmd.Parameters.Add("@Id", SqlDbType.Int).Direction =
                        ParameterDirection.Output;

                    con.Open();

                    bool isRowsAffected = saveCmd.ExecuteNonQuery() > 0;
                    if (isRowsAffected)
                    {
                        UserInfo ui = UserInfo.Select(userId);
                        if (ui != null)
                        {
                            HistoryRecord hr = new HistoryRecord
                            {
                                Action = HistoryEvent.Login,
                                Description =
                                    string.Format("Вход: {0} [host:{1}]/{2} {3} [admin:{4}, active:{5}]",
                                                  ui.Login, hostname, ui.FirstName, ui.LastName, ui.Admin, ui.Active)
                            };
                            hr.Insert();

                            string autologinValue = autologin ? "включен" : "отключен";

                            hr = new HistoryRecord
                            {
                                Action = HistoryEvent.Login,
                                Description =
                                    string.Format("Автовход {0}: {1} [host:{2}]",
                                                    autologinValue, ui.Login, hostname)
                            };
                            hr.Insert();
                        }
                    }

                    return isRowsAffected
                                ? Convert.ToInt32(saveCmd.Parameters["@Id"].Value)
                                : (int?)null;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }

        private static bool Update(int id, int userId, string hostname, bool autologin)
        {
            try
            {
                using (SqlConnection con = CommonDb.GetOilWizardConection())
                {
                    SqlCommand updCmd = new SqlCommand("LoginHostUpdate", con);
                    updCmd.CommandType = CommandType.StoredProcedure;

                    updCmd.Parameters.Add("@Id", SqlDbType.Int).Value = id;
                    updCmd.Parameters.Add("@Hostname", SqlDbType.VarBinary).Value = Crypto.Encrypt(hostname);
                    updCmd.Parameters.Add("@Autologin", SqlDbType.Bit).Value = autologin;
                    
                    con.Open();

                    bool isRowsAffected = updCmd.ExecuteNonQuery() > 0;
                    if (isRowsAffected)
                    {
                        LoginHost lh = Select(id);
                        UserInfo ui = UserInfo.Select(userId);
                        if (lh != null && ui != null)
                        {
                            HistoryRecord hr = new HistoryRecord
                            {
                                Action = HistoryEvent.Login,
                                Description =
                                    string.Format("Вход: {0} [host:{1}]/{2} {3} [admin:{4}, active:{5}]",
                                                  ui.Login, lh.Hostname, ui.FirstName, ui.LastName, ui.Admin, ui.Active)
                            };
                            hr.Insert();

                            string autologinValue = autologin ? "включен" : "отключен";
                            
                            hr = new HistoryRecord
                            {
                                Action = HistoryEvent.Login,
                                Description =
                                    string.Format("Автовход {0}: {1} [host:{2}]",
                                                    autologinValue, ui.Login, lh.Hostname)
                            };
                            hr.Insert();
                        }
                    }

                    return isRowsAffected;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return false;
            }
        }

        private static List<LoginHost> MapFrom(SqlDataReader dr)
        {
            try
            {
                if (dr != null && dr.HasRows)
                {
                    List<LoginHost> acList = new List<LoginHost>();
                    while (dr.Read())
                    {
                        LoginHost wt = new LoginHost
                        {
                            Id = Convert.ToInt32(dr["Id"]),
                            UserId = Convert.ToInt32(dr["UserId"]),
                            Hostname = Crypto.Decrypt((byte[])dr["Hostname"]),
                            Autologin = Convert.ToBoolean(dr["Autologin"]),
                            DateCreated = Convert.ToDateTime(dr["DateCreated"])
                        };

                        acList.Add(wt);
                    }
                    return acList;
                }
                return null;
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }
    }


}
